package it.uniroma2.controller;

import it.uniroma2.cloud.PROVIDER;

import java.util.Random;

public class Dispacher {

	private String location;

	private String[] CLOUD_LBS = new String[2];

	private static Dispacher instance;

	private static Random rnd = new Random(1001);

	private Dispacher() {
		CLOUD_LBS[0] = Controller.getInstance().getLoadBalancerAddress(
				PROVIDER.AWS_EC2);
		CLOUD_LBS[1] = Controller.getInstance().getLoadBalancerAddress(
				PROVIDER.OPENSTACK);
	}

	public static Dispacher getInstance() {
		if (instance == null) {
			instance = new Dispacher();
		}
		return instance;
	}

	public String getLocation() {
		int index = getBestLoad(); // OR getBestLatency(); OR getRandom();
		location = "http://" + CLOUD_LBS[index]
				+ "/imagetranscoder/transcoderServlet";
		return location;
	}

	public static int getRandom() {
		int index = -1;
		boolean next = rnd.nextBoolean();
		if (next)
			index = 1;
		else
			index = 0;
		return index;
	}	
	
	public static int getBestLoad() {
		ReporterChecker repChecker = ReporterChecker.getInstance();

		double loadAWS = repChecker.getMovingAverage_1MinLoad(PROVIDER.AWS_EC2);
		double loadOPENSTACK = repChecker
				.getMovingAverage_1MinLoad(PROVIDER.OPENSTACK);

		// howManyInstances
		double instancesNumAWS = repChecker.getInstancesNum(PROVIDER.AWS_EC2);
		double instancesNumOPENSTACK = repChecker
				.getInstancesNum(PROVIDER.OPENSTACK);
		// check data validity
		if (loadAWS != Double.NaN && loadOPENSTACK != Double.NaN
				&& instancesNumAWS != 0 && instancesNumOPENSTACK != 0) {
			// single workernodeload
			double realLoadAWS = loadAWS * instancesNumAWS;
			double realLoadOPENSTACK = loadOPENSTACK * instancesNumOPENSTACK;

			// check if we are in provisioning window
			if (loadAWS <= 0.9 || loadOPENSTACK <= 0.9) {
				if (realLoadAWS < realLoadOPENSTACK) {
					//System.out.print("D.AWS ");
					return 0;
				} else {
					//System.out.print("D.OPENSTACK ");
					return 1;
				}
			} else { // provisioning window
				//System.out.print("D.RANDOM ");
				return getRandom();
			}

		} else{
			//System.out.println("D.RANDOM ");
			return getRandom();
		}
	}

	public static int getBestLatency() {
		double latencyAWS = ReporterChecker.getInstance().getLatencyMean(
				PROVIDER.AWS_EC2);
		double latencyOPENSTACK = ReporterChecker.getInstance().getLatencyMean(
				PROVIDER.OPENSTACK);
		if (latencyAWS != Double.NaN && latencyOPENSTACK != Double.NaN) {
			if (latencyAWS < latencyOPENSTACK)
				return 0;
			else
				return 1;
		} else
			return getRandom();
	}

	public static void main(String[] args) {
		Dispacher dis = Dispacher.getInstance();
		for (int i = 0; i < 20; i++) {
			System.out.println(dis.getLocation());
		}
	}

}
